package com.augurit.common.dao;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.stereotype.Repository;

import com.augurit.common.base.dao.BaseDao;
import com.augurit.common.constant.OrgConstant;
import com.augurit.common.entity.AcApplication;
import com.augurit.common.entity.AcFunction;
import com.augurit.common.entity.AcMenu;
import com.augurit.common.system.convert.AcMenuConverter;
import com.augurit.common.system.util.OrgUtils;
import com.augurit.common.system.web.org.form.AcMenuForm;
import com.augurit.common.util.HqlUtils;
import com.augurit.common.util.lang.CollectionUtils;

/**
 * 菜单DAO类
 */
@Repository
public class AcMenuDao extends BaseDao<AcMenu, Long> {
	
	/**
	 * 保存应用系统Form对象
	 * @param form 应用系统Form对象
	 */
	public void save(AcMenuForm form){
		
		if(form != null){
			AcMenu entity = null;
			
			//准备VO对象
			if(form != null && form.getMenuId() != null){
				entity = this.get(form.getMenuId());
			}else{
				entity = new AcMenu();
			}
			
			//属性值转换
			AcMenuConverter.convertToEntity(form, entity);

			//如果用户设置了funcNo属性，则保存新的应用ID和功能ID
			OrgUtils.calcAppIdAndFuncId(form.getFuncNo(), entity);
			
			//保存
			super.save(entity);
			
			//回填ID属性值
			form.setMenuId(entity.getMenuId());
		}
	}
	
	/**
	 * 保存应用系统Form对象
	 * @param form 应用系统Form对象
	 */
	public void saveCascade(AcMenuForm form){
		
		if(form != null){
			AcMenu entity = null;
			
			//准备VO对象
			boolean isNewEntity = false;
			if(form != null && form.getMenuId() != null){
				entity = this.get(form.getMenuId());
			}else{
				entity = new AcMenu();
				isNewEntity = true;
			}
			
			//属性值转换
			AcMenuConverter.convertToEntity(form, entity);	
			
			//如果用户设置了funcNo属性，则保存新的应用ID和功能ID
			OrgUtils.calcAppIdAndFuncId(form.getFuncNo(), entity);
			
			//保存
			super.save(entity);
			
			//根据父菜单ID计算对象的层次、序列和所属应用ID等属性并保存
			updateAdditionalProperty(entity, isNewEntity);
			
			//回填ID属性值
			form.setMenuId(entity.getMenuId());
		}
	}

	/**
	 * 根据父菜单ID计算对象的层次、序列和所属应用ID等属性并保存
	 * @param entity
	 */
	public void updateAdditionalProperty(AcMenu entity, boolean isNewEntity){
		if(entity != null){
			
			//针对存在父节点的情况
			if(entity.getParentMenuId() != null){
				
				//获取父菜单对象
				AcMenu parentEntity = this.get(entity.getParentMenuId());
				
				entity.setMenuLevel(parentEntity.getMenuLevel() == null ? 1 : parentEntity.getMenuLevel() + 1);
				entity.setMenuSeq(parentEntity.getMenuSeq() + entity.getMenuId() + ".");
				
				if(isNewEntity){
					parentEntity.setIsLeaf(OrgConstant.ZERO);
					parentEntity.setSubCount((parentEntity.getSubCount() == null ? 0 : parentEntity.getSubCount().intValue()) + 1);
				}
				
				super.save(parentEntity);
			}
			//针对无父节点的情况
			else{
				entity.setMenuLevel(1);
				entity.setMenuSeq("." + entity.getMenuId() + ".");
				//entity.setIsLeaf(OrgConstant.ZERO);	//此处王剑文2010-03-08注释
				entity.setSubCount(0);
			}
			
			super.save(entity);
		}
	}
	
	/**
	 * 获取指定菜单对象及其所有子菜单
	 * @param menuId
	 * @return
	 */
	public List<AcMenu> getAllChildMenus(Long menuId){
		if(menuId != null){
			String hql = "from AcMenu ps where ps.menuSeq like ?";
			List values = new ArrayList();
			values.add("%." + menuId + ".%");
			return this.find(hql, values);
		}else
			return null;
	}
	
	/**
	 * 级联删除菜单
	 * @param menuId
	 */
	public void deleteMenuCasCade(Long menuId){
		List<AcMenu> entities = getAllChildMenus(menuId);
		if(entities != null && entities.size() > 0){
			this.delete(entities);
		}
	}
	
	/**
	 * 改变菜单的应用系统地址
	 * @param entity
	 * @param newAppUrl
	 */
	public void changeAppUrl(AcApplication entity, String newAppUrl){
		if(entity != null)
			changeAppUrl(entity.getAppId(), entity.getAppUrl(), newAppUrl);
	}
	
	/**
	 * 改变菜单的应用系统地址
	 * @param oldAppUrl
	 * @param newAppUrl
	 */
	public void changeAppUrl(Long appId, String oldAppUrl, String newAppUrl){
		//如果为空则表示本地应用
		String tempOldAppUrl = oldAppUrl != null && oldAppUrl.trim().length() > 0 ? oldAppUrl + "/" : "";
		String tempNewAppUrl = newAppUrl != null && newAppUrl.trim().length() > 0 ? newAppUrl + "/" : "";
		
		String hql = "from AcMenu ps where ps.menuUrl like '" + tempOldAppUrl + "%' and ps.appId = " + appId;
		List<AcMenu> list = this.find(hql);
		
		if(list != null && list.size() > 0){
			for(AcMenu menu : list){
				String newMenuUrl = "";
				if(tempOldAppUrl.equals(""))
					newMenuUrl = tempNewAppUrl;
				else
					newMenuUrl = menu.getMenuUrl().replace(tempOldAppUrl, tempNewAppUrl);
				menu.setMenuUrl(newMenuUrl);
				this.save(menu);
			}
		}
	}
	
	/**
	 * 改变菜单的功能访问地址
	 * @param entity
	 * @param newFuncUrl
	 */
	public void changeRelatedMenuUrl(AcFunction entity, String newFuncUrl){
		
		String hql = "from AcMenu ps where ps.funcId=?";
		List<AcMenu> list = this.find(hql, entity.getFuncId());
		
		if(list != null && list.size() > 0){
			for(AcMenu menu : list){
				if(newFuncUrl.startsWith("javascript:") || newFuncUrl.startsWith("http://"))
					menu.setMenuUrl(newFuncUrl);
				else
					menu.setMenuUrl(getAppUrl(entity.getModuleId()) + newFuncUrl);
				this.save(menu);
			}
		}		
	}
	
	private String getAppUrl(Long moduleId){
		String hql = "select distinct app.appUrl from AcApplication app, AcModule mod where app.appId=mod.appId and mod.moduleId=?";
		List<String> list = this.find(hql, moduleId);
		if(list != null && list.size() == 1)
			return list.get(0);
		else
			return null;
	}

	public void disAssociateWithFunc(Long funcId){
		if(funcId != null){
			String hql = "from AcMenu ps where ps.funcId = ?";
			List values = new ArrayList();
			values.add(funcId);
			List<AcMenu> list = this.find(hql, values);
			
			if(list != null && list.size() > 0){
				for(AcMenu entity : list){
					entity.setAppId(null);
					entity.setFuncId(null);
					entity.setMenuUrl(null);
					this.save(entity);
				}
			}
		}
	}
	
	/**
	 * 获取指定菜单对应的功能id
	 * @param menuId 菜单id 
	 * @return 功能id
	 */
	public Long getRelatedFuncIdByMenuId(Long menuId){
		if(menuId != null){
			String hql = "select ps.funcId from AcMenu ps where ps.menuId=?";
			List values = new ArrayList();
			values.add(menuId);
			return this.findUnique(hql, values);			
		}
		return null;
	}
	
	/**
	 * 根据功能id获取所有关联菜单名称，以'、'号连接菜单名
	 * @funcId 指定功能id
	 * @return 与功能id获取所有关联菜单名称
	 * */
	public String getMenuNamesByFuncId(Long funcId){
		String menuNames = "";
		
		if(funcId != null){
			String hql = "from AcMenu ps where ps.funcId=?";
			List<Long> values = new ArrayList();
			values.add(funcId);
			List<AcMenu> list = this.find(hql, values);
			
			if(list != null && list.size() > 0){
				for(int i=0; i<list.size(); i++){
					String name = OrgUtils.getMenuNameWithActiveFlag(list.get(i));
					menuNames += i == 0 ? name : OrgConstant.STRING_SEPARATOR_D + name;
				}
			}
		}
		
		return menuNames;
	}
	
	/**
	 * 根据功能Id集合获取关联的菜单
	 * @param funcIds 功能id
	 * @return 功能forms
	 */
	public List<AcMenuForm> getRelatedMenusByFuncIds(Long[] funcIds){
		if(funcIds != null && funcIds.length > 0){
			Long[] menuIds = getAllRelatedMenuIds(funcIds);
			return this.get(menuIds);
		}
		return null;
	}

	public List<AcMenuForm> get(Long[] menuIds){
		if(menuIds != null && menuIds.length > 0){
			String hql = "from AcMenu ps where " + HqlUtils.buildOrCondition("ps", "menuId", menuIds);
			List<AcMenu> list = this.find(hql);
			return AcMenuConverter.convertToForm(list);
		}else
			return null;
	}
	
	/**
	 * 根据功能ID集合获取关联的菜单ID集合
	 * 注意：如果某菜单存在父菜单，则同时也会返回其所有关联的父菜单列表
	 * @param funcIds
	 * @return
	 */
	public Long[] getAllRelatedMenuIds(Long[] funcIds){
		Set<Long> menuIdsSet = new HashSet<Long>();
		
		if(funcIds != null && funcIds.length > 0){
			String hql = "select menu.menuSeq from AcMenu menu, AcFunction func where menu.funcId = func.funcId and "
				+ HqlUtils.buildOrCondition("func", "funcId", funcIds);
			List<String> list = this.find(hql);
			
			if(list != null && list.size() > 0){
				for(String menuSeq : list){
					String[] menuIds = OrgUtils.splitSeqToArray(menuSeq);
					menuIdsSet.addAll(CollectionUtils.toLongList(menuIds));
				}
			}
		}
		
		return CollectionUtils.toLongArray(menuIdsSet);
	}
}
